﻿using CPPEI.App;
using CPPEI.Coolzon.Common;
using CPPEI.Coolzon.Common.Startup;
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Text;
using System.Windows;

namespace CPPEI.WPF.Core
{
    /// <summary>
    /// 应用程序的父类，
    /// 父类中完成了，应用程序注册表信息的写入，以及对更新程序的调用,
    /// 当应用程序的启动参 /update no 时将不会启动更新程序
    /// </summary>
    public class XApplication : Application
    {
        /// <summary>
        /// 获取当前AppDomain中的应用程序实例
        /// </summary>
        public static XApplication XCurrent
        {
            get
            {
                return Current as XApplication;
            }
        }

        public string Company { get; private set; }

        public string Product { get; private set; }

        /// <summary>
        /// 应用程序类型名称
        /// </summary>
        public string AppType { get; private set; }

        /// <summary>
        /// 应用程序的名称
        /// </summary>
        public string AppName { get; private set; }

        /// <summary>
        /// 更新程序的类型名称
        /// </summary>
        public string UpdateAppType { get; private set; }

        public Version Version { get; private set; }

        /// <summary>
        /// 应用程序信息
        /// </summary>
        public AppInfo AppInfo { get; private set; }

        /// <summary>
        /// 程序启动参数
        /// </summary>
        public StartupParamCollection StartupParams { get; private set; }

        /// <summary>
        /// 只有在构造函数里设置才有效果
        /// </summary>
        public XApplicationSettings Settings { get; private set; }

        System.Threading.Mutex _mutex;

        /// <summary>
        /// 构造应用程序,Company和Product信息将从Assembly信息中读取
        /// </summary>
        /// <param name="appType">应用程序类型</param>
        /// <param name="appName">应用程序名称</param>
        private XApplication(string appType, string appName)
        {
            System.Reflection.Assembly entryAssembly = System.Reflection.Assembly.GetEntryAssembly();
            AssemblyProductAttribute productAttr = (AssemblyProductAttribute)Attribute.GetCustomAttribute(entryAssembly, typeof(AssemblyProductAttribute));
            AssemblyCompanyAttribute companyAttr = (AssemblyCompanyAttribute)Attribute.GetCustomAttribute(entryAssembly, typeof(AssemblyCompanyAttribute));

            this.Company = companyAttr.Company;
            this.Product = productAttr.Product;
            this.AppType = appType;
            this.AppName = appName;
            this.Version = entryAssembly.GetName().Version;
        }

        /// <summary>
        /// 构造应用程序，此程序不会启动更新程序
        /// </summary>
        /// <param name="company">公司名称</param>
        /// <param name="product">产品名称</param>
        /// <param name="appType">应用程序类型</param>
        /// <param name="appName">应用程序名称</param>
        public XApplication(string company, string product, string appType, string appName)
        {
            Company = company;
            Product = product;
            AppType = appType;
            AppName = appName;
            System.Reflection.Assembly entryAssembly = System.Reflection.Assembly.GetEntryAssembly();
            this.Version = entryAssembly.GetName().Version;

            // 初始化程序设置
            Settings = new XApplicationSettings();
        }

        /// <summary>
        /// 构造应用程序,此程序需要启动更新程序
        /// </summary>
        /// <param name="company">公司名称</param>
        /// <param name="product">产品名称</param>
        /// <param name="appType">应用程序类型</param>
        /// <param name="appName">应用程序名称</param>
        /// <param name="appName">更新应用程序名称</param>
        public XApplication(string company, string product, string appType, string appName, string updateAppType)
            : this(company, product, appType, appName)
        {
            this.UpdateAppType = updateAppType;
        }


        /// <summary>
        /// Raises the System.Windows.Application.Startup event.
        /// </summary>
        /// <param name="e"></param>
        protected override void OnStartup(StartupEventArgs e)
        {
            base.OnStartup(e);

            AppInfo = CoolzonRegistryUtil.GetAppInfo(this.Company, this.Product, this.AppType);
            if (AppInfo == null)
            {
                #region 写入注册表信息

                AppInfo = new CPPEI.Coolzon.Common.AppInfo();
                AppInfo.Company = this.Company;
                AppInfo.Product = this.Product;
                AppInfo.Type = AppType;
                AppInfo.Name = AppName;
                AppInfo.Directory = AppDomain.CurrentDomain.BaseDirectory;
                System.Reflection.Assembly entryAssembly = System.Reflection.Assembly.GetEntryAssembly();
                AppInfo.AppFile = entryAssembly.Location;
                AppInfo.Version = entryAssembly.GetName().Version;

                Logger.Info("启动程序,{0}", AppInfo.ToString());
                CoolzonRegistryUtil.SaveAppInfo(this.Company, this.Product, AppInfo);

                #endregion
            }
            else
            {
                System.Reflection.Assembly entryAssembly = System.Reflection.Assembly.GetEntryAssembly();
                Version curVersion = entryAssembly.GetName().Version;

                if (curVersion >= AppInfo.Version)
                {
                    AppInfo = new CPPEI.Coolzon.Common.AppInfo();
                    AppInfo.Company = this.Company;
                    AppInfo.Product = this.Product;
                    AppInfo.Type = AppType;
                    AppInfo.Name = AppName;
                    AppInfo.AppFile = entryAssembly.Location;
                    AppInfo.Version = curVersion;
                    AppInfo.Directory = AppDomain.CurrentDomain.BaseDirectory;

                    Logger.Info("启动程序,{0}", AppInfo.ToString());
                    CoolzonRegistryUtil.SaveAppInfo(this.Company, this.Product, AppInfo);
                }
                else
                {
                    Logger.Error("启动程序失败,程序版本低于已注册的版本信息,程序关闭,{0}", AppInfo.ToString());
                    this.ShutdownMode = System.Windows.ShutdownMode.OnExplicitShutdown;
                    this.Shutdown();
                    return;
                }
            }

            bool isContinueRun = true;

            #region 设置单例运行
            if (Settings.IsSingleton)
            {
                System.Reflection.Assembly entryAssembly = System.Reflection.Assembly.GetEntryAssembly();
                if (System.Threading.Mutex.TryOpenExisting(entryAssembly.GetName().Name, out _mutex))
                {
                    // 已存在
                    Logger.Error("启动程序失败,已有实例正在运行");
                    this.ShutdownMode = System.Windows.ShutdownMode.OnExplicitShutdown;
                    this.Shutdown();
                    isContinueRun = false;
                }
                else
                {
                    _mutex = new System.Threading.Mutex(true, entryAssembly.GetName().Name);
                }
            }
            #endregion

            // 读取启动参数
            StartupParams = StartupUtil.Parse(e.Args);

            if (false)
            {
                if (!string.IsNullOrEmpty(UpdateAppType))
                {
                    // 判断是否需要启动更新程序
                    if (StartupParams.GetValue("update") != "NO")
                    {
                        // 启动更新程序
                        // 检查更新
                        AppInfo updateAppInfo = Coolzon.Common.CoolzonRegistryUtil.GetAppInfo(this.Company, this.Product, this.UpdateAppType);
                        if (updateAppInfo != null)
                        {
                            StartupAppUtil.StartupApp(updateAppInfo, string.Format("/p {0}", AppInfo.Type));

                            // 关闭当前程序
                            this.ShutdownMode = System.Windows.ShutdownMode.OnExplicitShutdown;
                            this.Shutdown();
                            return;
                        }
                        else
                        {
                            Coolzon.Common.Logger.WarningToTag("WPF.Core", "获取更新程序:{0}出错,无法进行更新程序继续运行!", this.UpdateAppType);
                            OnXStartup(StartupParams);
                        }
                    }
                    else
                    {
                        OnXStartup(StartupParams);
                    }
                }
                else
                {
                    OnXStartup(StartupParams);
                }
            }
            else if(isContinueRun)
            {
                OnXStartup(StartupParams);
            }
        }

        protected virtual void OnXStartup(StartupParamCollection startupParams)
        {
        }

        /// <summary>
        /// 启动更新程序,并退出程序自身
        /// </summary>
        public void StartUpdateAppAndShutdown()
        {
            if (!string.IsNullOrEmpty(UpdateAppType))
            {
                // 启动更新程序
                // 检查更新
                AppInfo updateAppInfo = Coolzon.Common.CoolzonRegistryUtil.GetAppInfo(this.Company, this.Product, this.UpdateAppType);
                if (updateAppInfo != null)
                {
                    StartupAppUtil.StartupApp(updateAppInfo, string.Format("/p {0} /restart y", AppInfo.Type));

                    // 关闭当前程序
                    this.ShutdownMode = System.Windows.ShutdownMode.OnExplicitShutdown;
                    this.Shutdown();
                }
                else
                {
                    Coolzon.Common.Logger.WarningToTag("WPF.Core", "获取更新程序:{0}出错,无法进行更新程序继续运行!", this.UpdateAppType);
                }
            }
            else
            {
                Coolzon.Common.Logger.WarningToTag("WPF.Core", "获取更新程序,没有定义更新程序的名称");
            }
        }
    }
}
